﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Data;
using SL.MVVMS.RIA;
using MVVM_S.Samples.HelpDesk.Services;
using MVVM_S.Samples.HelpDesk.Web.Models;
using System.Windows;
using System.Collections.Specialized;

namespace MVVM_S.Samples.HelpDesk.ViewModels
{
    /// <summary>
    /// This is a basic ViewModel Template using the MVVM-S Toolkit
    /// ViewModels inherit from the ViewModel base class, and implement
    /// service classes as needed, which provide data to the View Model
    /// You Should be able to assume that operations in the ViewModel 
    /// all occur on the UI thread, since the ServiceModel deals with
    /// threading.  Also, data should be blendable, if your service 
    /// implements a design data template as well.
    /// 
    /// Use the <see cref="slvmprop">slvmprop</see> snippet to create Properties in the ViewModel
    /// Use the <see cref="slvmcollection">slvmcollection</see> snippet to expose Collections
    /// Use the <see cref="slvmcmd">slvmcmd</see> snippet to create Commands in the ViewModel
    /// </summary>
    public class TicketViewModel : ViewModel
    {
        HelpdeskService dataService;
        public TicketViewModel()
        {
            dataService = new HelpdeskService();

            // DONE: Add setupCommand and setupCollection functions here
            // to construct those items as needed
            setupNoteListCollection();
            setupCmdResolve();
            setupCmdAddNote();
            setupCmdDelete();
            setupCmdSave();
            setupCmdUndo();
            setupNotifications();

            if (DesignerProperties.IsInDesignTool)
                SelectedTicket = dataService.Tickets.First();
        }

        /// <summary>
        /// Add this to your Constructor in your View Model
        /// </summary>
        void setupNotifications()
        {
            SL.MVVMS.RIA.Notifications.ReceiveNotification +=
                new WeakEventHandler<NotificationEventArg>(notification_Received).Handler;
        }

        /// <summary>
        /// Process all your Notifications Here
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void notification_Received(object sender, NotificationEventArg args)
        {
            // Note: This must be public to allow the WeakEventHandler
            // to provide the delegate

            // DONE: Process Messages Recieved Here
            if (args.Message == "Lookups Refreshed")
            {
                RaisePropertyChanged("SelectedTicket");
                NoteList.Refresh();
            }
        }


        // DONE: Use the snippets slvmprop, slvmcollection, and slvmcmd to create 
        // Properties, Collections, and Commands for your View to bind to

        
        Ticket _SelectedTicket;
        public Ticket SelectedTicket
        {
            get { return _SelectedTicket; }
            set
            {
                if (_SelectedTicket != value)
                {
                    _SelectedTicket = value;
                    RaisePropertyChanged("SelectedTicket");
                }
                if (_SelectedTicket != null)
                {
                    NoteList.Filter += (obj) =>    // Update the filter
                    {
                        Note item = obj as Note;
                        if (item == null)
                            return false;

                        // Apply your Filtering Logic Here by inspecting the Note item.
                        if (item.Ticket == SelectedTicket)
                            return true;
                        else
                            return false;
                    };
                }
            }
        }

        
        #region NoteList - Collection of Note
        /// <summary>
        /// Bind to this property in your View
        /// </summary>
        public PagedCollectionView NoteList { get; private set; }

        /// <summary>
        /// Call this from your constructor to create the View on load
        /// </summary>
        void setupNoteListCollection()
        {
            NoteList = new PagedCollectionView(dataService.Notes);
            using (NoteList.DeferRefresh())
            {
                // Use these examples to get started with Sorting, Grouping and Filtering
                NoteList.SortDescriptions.Add(      // Apply Sorting
                   new SortDescription("Entered", ListSortDirection.Descending));
                // NoteList.GroupDescriptions.Add(     // Apply Grouping
                //    new PropertyGroupDescription("PropertyName"));
                NoteList.Filter += (obj) =>    // Apply a filter
                   {
                       Note item = obj as Note;
                       if (item == null)
                           return false;

                       // Return Nothing until something is selected
                       return false;
                   };
            }
        }

        // COMMENTED OUT - This is not Needed, since we show Related Note Items
        ///// <summary>
        ///// Call this to Load and Refresh the NoteList of Note data afterwards
        ///// </summary>
        //void loadNoteListCollection()
        //{
        //    dataService.LoadCustomers(() =>
        //        {
        //            NoteList.Refresh();
        //        });
        //}
        #endregion
                

        #region Functions to Load a Ticket
        
        public void LoadTicket(int ticketID)
        {
            dataService.LoadTicketDetails(ticketID, () =>
                {
                    SelectedTicket = dataService.Tickets
                        .SingleOrDefault(t => t.TicketID == ticketID);
                });
        }
         
        public void NewTicket()
        {
            SelectedTicket = new Ticket()
            {
                TicketID = 0,
                UpdatedBy = 1,
                Opened = DateTime.Now,
                Updated = DateTime.Now,
                EscalationLevel = 0,
                Title = "<New Ticket>"
            };
            dataService.Add(SelectedTicket);
        }

        #endregion

        #region Commands

        
        /// <summary>
        /// Bindable Command from your View
        /// </summary>
        public ViewModelCommand CmdResolve { get; private set; }

        /// <summary>
        /// Call this from your constructor 
        /// </summary>
        void setupCmdResolve()
        {
            CmdResolve = new ViewModelCommand(() =>
                {
                    // Provide your implementation here
                    SelectedTicket.Resolved = DateTime.Now;
                    SelectedTicket.ResolvedBy = 1;
                }
                , () =>
                {
                    // Determine when the Command is Active Here
                    if (SelectedTicket != null)
                        return true;
                    else
                        return false;
                }
                );
        }
                
        
        /// <summary>
        /// Bindable Command from your View
        /// </summary>
        public ViewModelCommand CmdSave { get; private set; }

        /// <summary>
        /// Call this from your constructor 
        /// </summary>
        void setupCmdSave()
        {
            CmdSave = new ViewModelCommand(() =>
                {
                    // Provide your implementation here
                    dataService.Save(() =>
                        {
                            MessageBox.Show("Ticket Saved!");
                        });
                }
                //,() =>
                //{
                //    // Determine when the Command is Active Here
                //     if (SelectedItem != null)
                //         return true;
                //     else
                //         return false;
                //}
                );
        }

        
        /// <summary>
        /// Bindable Command from your View
        /// </summary>
        public ViewModelCommand CmdUndo { get; private set; }

        /// <summary>
        /// Call this from your constructor 
        /// </summary>
        void setupCmdUndo()
        {
            CmdUndo = new ViewModelCommand(() =>
                {
                    // Provide your implementation here
                    dataService.Undo();
                }
                , () =>
                {
                    // Determine when the Command is Active Here
                    if (SelectedTicket == null)
                        return false;
                    if (SelectedTicket.EntityState != System.ServiceModel.DomainServices.Client.EntityState.New)
                        return true;
                    else
                        return false;
                }
                );
        }

        
        /// <summary>
        /// Bindable Command from your View
        /// </summary>
        public ViewModelCommand CmdDelete { get; private set; }

        /// <summary>
        /// Call this from your constructor 
        /// </summary>
        void setupCmdDelete()
        {
            CmdDelete = new ViewModelCommand(() =>
                {
                    // Provide your implementation here
                    dataService.Delete(SelectedTicket);
                }
                , () =>
                {
                    // Determine when the Command is Active Here
                    if (SelectedTicket == null)
                        return false;
                    if (SelectedTicket.EntityState != System.ServiceModel.DomainServices.Client.EntityState.New)
                        return true;
                    else
                        return false;
                }
                );
        }

        
        /// <summary>
        /// Bindable Command from your View
        /// </summary>
        public ViewModelCommand CmdAddNote { get; private set; }

        /// <summary>
        /// Call this from your constructor 
        /// </summary>
        void setupCmdAddNote()
        {
            CmdAddNote = new ViewModelCommand(() =>
                {
                    // Provide your implementation here

                    Windows.NoteEditorWindow noteWindow = new Windows.NoteEditorWindow();
                    noteWindow.Closed += (s, a) =>
                        {
                            if (noteWindow.DialogResult.HasValue &&
                                noteWindow.DialogResult.Value)
                            {
                                Note newNote = new Note()
                                {
                                    Ticket = SelectedTicket,
                                    Entered = DateTime.Now,
                                    Text = noteWindow.NoteText,
                                    EnteredBy = "Joe User" //The following would be better WebContext.Current.User.DisplayName
                                };
                                dataService.Add(newNote);
                                NoteList.Refresh();
                            }
                        };
                    noteWindow.Show();

                }
                //,() =>
                //{
                //    // Determine when the Command is Active Here
                //     if (SelectedItem != null)
                //         return true;
                //     else
                //         return false;
                //}
                );
        }
                

        #endregion

    }
}

